/* AndyDroid - Android automation testing Framework.
 Copyright (C) 2011 MicroStrategy Test Automation Team

 AndyDroid is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with software. If not, contact us.
 
 @email:	robort1002@gmail.com
 */
package com.microstrategy.android.automation.tester;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import android.app.Activity;
import android.app.Instrumentation;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;

import com.microstrategy.android.automation.Logger;
import com.microstrategy.android.automation.utils.ViewUtils;
import com.microstrategy.android.automation.view.ViewController;
import com.microstrategy.android.automation.view.ViewCoordinate;

/**
 * Base class for all view elements in Andy.
 * 
 * 
 */
public class ViewTester implements IViewTester {
	private static final String LOG_TAG = "AndyView";

	protected Instrumentation inst;
	protected Activity activity;
	protected ViewController viewOperation;
	private View view;
	
	private static int maxTimeToFindView = ANR_TIME;

	/**
	 * Constructor of AndyView.
	 * @param inst Instrumentation.
	 * @param view {@code View} or its subclass.
	 */
	public ViewTester(Instrumentation inst, View view, Activity activity) {
		this.inst = inst;
		this.viewOperation = new ViewController(inst);
		this.view = view;
		this.activity = activity;
	}

	@SuppressWarnings("deprecation")
	@Override
	public void doClick() {
		
		//we need to wait for a view to be shown
		final long startTime = System.currentTimeMillis();
		while (System.currentTimeMillis() < startTime + getMaxTimeToFindView()) {
			if (view.getVisibility() == View.VISIBLE) {
				break;				
			} else {
				sleep(RETRY_TIME);
			}
		}
		
		if (null == view) {
			Logger.e(LOG_TAG, "View is null, doClick() failed");
		}
		
		try {
			viewOperation.clickOnView(view, false);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("deprecation")
	@Override
	public void doLongClick() {

		if (null == view) {
			Logger.e(LOG_TAG, "View is null, doLongClick() failed");
		}
		
		try {
			viewOperation.clickOnView(this.view, true);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void requestFocus() {
		inst.waitForIdleSync();
		inst.runOnMainSync(new Runnable() {

			@Override
			public void run() {
				view.requestFocus();
			}
		});
		inst.waitForIdleSync();

	}

	@Override
	public boolean isEnabled() {
		return view.isEnabled();
	}

	@Override
	public boolean isSelected() {
		return view.isSelected();
	}

	@Override
	public boolean isDisplayed() {
		return view.hasWindowFocus() && view.isEnabled() && view.isShown()
				&& (getWidth() > 0) && (getHeight() > 0);
	}

	@Override
	public int getId() {
		return view.getId();
	}

	@Override
	public int getWidth() {
		return view.getWidth();
	}

	@Override
	public int getHeight() {
		return view.getHeight();
	}

	@Override
	public ViewCoordinate getLocation() {
		int[] location = new int[2];
		view.getLocationOnScreen(location);
		return new ViewCoordinate(location[0], location[1]);
	}

	

	@Override
	public void scrollTo(final int x, final int y) {
		inst.waitForIdleSync();
		inst.runOnMainSync(new Runnable() {
			
			@Override
			public void run() {
				view.scrollTo(x, y);
			}
		});
		inst.waitForIdleSync();
	}

	@Override
	public void scrollBy(final int x, final int y) {
		inst.waitForIdleSync();
		inst.runOnMainSync(new Runnable() {
			
			@Override
			public void run() {
				view.scrollBy(x, y);
			}
		});
		inst.waitForIdleSync();
	}

	protected int getScreenHeight() {
		return ViewUtils.getScreenHeight(activity);
	}
	
	protected int getScreenWidth() {
		return ViewUtils.getScreenWidth(activity);
	}
	
	protected static void sleep(int time) {
		try {
			Thread.sleep(time);
		} catch (InterruptedException ignored) {
			ignored.printStackTrace();
		}
	}
	
	public static final void setMaxTimeToFindView(int maxTime) {
		maxTimeToFindView = maxTime;
	}
	
	protected int getMaxTimeToFindView() {
		return maxTimeToFindView;
	}
}
